package cn.larry.aop.config.advice;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;

@Profile("within")
@Aspect
@Component
public class WithinAdvice {

	/**
	 * 在方法执行之前。
	 */
	@Before("cn.larry.aop.config.aspect.WithinAspect.withinServiceLayer()")
	public void before() {
		System.out.println("----hello from cn.larry.aop.config.advice.WithinAdvice.before()");
	}

	/**
	 * 在方法正常结束之后（非异常）。 可以操作方法的返回结果--可选。
	 */
	@AfterReturning(pointcut = "cn.larry.aop.config.aspect.WithinAspect.withinServiceLayer()", returning = "retVal")
	public void afterReturning(Object retVal) { // 如果是String retVal，那相当于给pointcut加了返回类型的约束。
		System.out.println("----hello from cn.larry.aop.config.advice.WithinAdvice.afterReturning()");
		System.out.println(retVal);
	}

	/**
	 * 在方法抛出异常之后。异常可选。
	 */
	@AfterThrowing(pointcut = "cn.larry.aop.config.aspect.WithinAspect.withinServiceLayer()", throwing = "ex")
	public void afterThrowing(Exception ex) { // 同样给pointcut添加了约束：抛出该类型的异常。
		System.out.println("----hello from cn.larry.aop.config.advice.WithinAdvice.afterThrowing()");
		System.out.println(ex);
	}

	/**
	 * 只要方法执行结束！
	 */
	@After("cn.larry.aop.config.aspect.WithinAspect.withinServiceLayer()")
	public void after() {
		System.out.println("----hello from cn.larry.aop.config.advice.WithinAdvice.after()");
	}

	/**
	 * 环绕方法执行。不对，没有考虑抛出异常的情况！异常时应该怎么处理？
	 * 
	 * @param jp
	 */
	@Around("cn.larry.aop.config.aspect.WithinAspect.withinServiceLayer()")
	public Object around(ProceedingJoinPoint jp) { // 注意，必须有返回。
		System.out.println("----hello from cn.larry.aop.config.advice.WithinAdvice.around() start");
		Object proceed = null;
		try {
			proceed = jp.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		System.out.println("----hello from cn.larry.aop.config.advice.WithinAdvice.around() end");
		return proceed;
	}
}
